package com.tyc.c10;

import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.StaticMethodMatcherPointcut;
import java.lang.reflect.Method;

/**
 * 测试 Spring 如何选择代理
 *      a. proxyTargetClass = false 目标类实现接口用 JDK
 *      b. proxyTargetClass = false 目标类未实现接口用 cglib
 *      c. proxyTargetClass = true 用 cglib
 */
public class ApplicationC10 {
    public static void main(String[] args) throws NoSuchMethodException {

        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        // 根据方法名进行匹配
        pointcut.setExpression("execution(* foo())");
        boolean foo = pointcut.matches(T1.class.getMethod("foo"), T1.class);
        System.out.println(foo);
        // 根据方法上注解进行匹配
        pointcut.setExpression("@annotation(注解的全路径类名)");
        // 自定义匹配
        StaticMethodMatcherPointcut p2 = new StaticMethodMatcherPointcut() {
            @Override
            public boolean matches(Method method, Class<?> aClass) {
                // 自定义匹配逻辑
                return false;
            }
        };
//        // 准备切点
//        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
//        pointcut.setExpression("execution(* foo())");
//        // 准备通知
//        MethodInterceptor advice = invocation ->{
//            System.out.println("before");
//            Object result = invocation.proceed();
//            System.out.println("after");
//            return result;
//        };
//        // 准备切面
//        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);
//        // 创建代理
//        T1 t1 = new T1();
//        ProxyFactory proxyFactory = new ProxyFactory();
//        proxyFactory.setTarget(t1);
//        proxyFactory.setProxyTargetClass(true); //默认为false
//        proxyFactory.addAdvisor(advisor);
//        proxyFactory.setInterfaces(t1.getClass().getInterfaces());
//        I1 p = (I1)proxyFactory.getProxy();
//        System.out.println(p.getClass());
//        p.foo();
//        p.bar();
    }

    interface I1{
        void foo();
        void bar();
    }

    static class T1 implements I1{

        @Override
        public void foo() {
            System.out.println("t1 foo");
        }

        @Override
        public void bar() {
            System.out.println("t1 bar");
        }
    }

    static class T2 implements I1{

        @Override
        public void foo() {
            System.out.println("t2 foo");
        }

        @Override
        public void bar() {
            System.out.println("t2 bar");
        }
    }
}
